﻿using BlogSystem.Services.Attributes;
using BookStore.DataLayer;
using BookStore.Models;
using BookStore.Services.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Web.Http.ValueProviders;

namespace BookStore.Services.Controllers
{
    public class BooksController : BaseApiController
    {
        [ActionName("all")]
        public IQueryable<BookModel> GetAll()
        {
            var responseMsg = this.PerformOperationAndHandleExceptions(() =>
            {
                var context = new BookstoreContext();

                var bookEntities = context.Books;
                var models =
                    (from bookEntity in bookEntities
                     select new BookModel()
                     {
                         Id = bookEntity.Id,
                         Title = bookEntity.Title,
                         Author = bookEntity.Author,
                         Store = bookEntity.Store.StoreName,
                         Genre = bookEntity.Genre,
                         RentCost = bookEntity.RentCost,
                         Pages = bookEntity.Pages,
                         IsAvailable = bookEntity.IsAvailable ? "True" : "False"
                     });

                return models;
            });

            return responseMsg;
        }

        //public IQueryable<BookModel> GetByAuthor(string author)
        //{
        //    var models = this.GetAll()
        //        .Where(b => b.Author.ToLower().Contains(author.ToLower()));
        //    return models;
        //}

        public IQueryable<BookModel> GetByGenre(string genre)
        {
            var models = this.GetAll()
                .Where(b => b.Genre.ToLower().Equals(genre.ToLower()));
            return models;
        }

        [ActionName("free")]
        public IQueryable<BookModel> GetFree()
        {
            var models = this.GetAll()
                .Where(b => b.IsAvailable.Equals("True"));
            return models;
        }

        [ActionName("rent")]
        public HttpResponseMessage PutRent(int bookId,
            [ValueProvider(typeof(HeaderValueProviderFactory<string>))] string sessionKey)
        {
            var responseMsg = this.PerformOperationAndHandleExceptions(
              () =>
              {
                  var context = new BookstoreContext();
                  using (context)
                  {
                      var user = context.Users.FirstOrDefault(
                          usr => usr.SessionKey == sessionKey);

                      if (user == null)
                      {
                          throw new InvalidOperationException("Invalid sessionKey");
                      }

                      var book = context.Books.FirstOrDefault(x => x.Id == bookId);

                      if (book == null || !book.IsAvailable)
                      {
                          throw new InvalidOperationException("Invalid book");
                      }

                      book.IsAvailable = false;

                      var record = new BookRecord()
                      {
                          BookId = book.Id,
                          UserId = user.Id,
                          RentDate = DateTime.Now,
                          ReturnedDate = null
                      };

                      user.BookRecords.Add(record);
                      
                      context.SaveChanges();

                      var response =
                          this.Request.CreateResponse(HttpStatusCode.OK);
                      return response;
                  }
              });

            return responseMsg;
        }

        [ActionName("return")]
        public HttpResponseMessage PutReturn(int bookId,
            [ValueProvider(typeof(HeaderValueProviderFactory<string>))] string sessionKey)
        {
            var responseMsg = this.PerformOperationAndHandleExceptions(
              () =>
              {
                  var context = new BookstoreContext();
                  using (context)
                  {
                      var user = context.Users.FirstOrDefault(
                          usr => usr.SessionKey == sessionKey);

                      if (user == null)
                      {
                          throw new InvalidOperationException("Invalid sessionKey");
                      }

                      var book = context.Books.FirstOrDefault(x => x.Id == bookId);

                      if (book == null || book.IsAvailable)
                      {
                          throw new InvalidOperationException("Invalid book");
                      }

                      book.IsAvailable = true;
                      var record = context.BookRecords.FirstOrDefault(
                          x => x.UserId == user.Id && x.BookId == book.Id);

                      if (record == null)
                      {
                          throw new InvalidOperationException("Invalid record");
                      }

                      record.ReturnedDate = DateTime.Now;
                      context.SaveChanges();

                      var response =
                          this.Request.CreateResponse(HttpStatusCode.OK);
                      return response;
                  }
              });

            return responseMsg;
        }

        public HttpResponseMessage PostBook(BookModel model,
            [ValueProvider(typeof(HeaderValueProviderFactory<string>))] string sessionKey)
        {
            var responseMsg = this.PerformOperationAndHandleExceptions(
                () =>
                {
                    var context = new BookstoreContext();
                    using (context)
                    {
                        var user = context.Users.FirstOrDefault(
                            usr => usr.SessionKey == sessionKey);
                        if (user == null || !user.IsAdmin)
                        {
                            throw new InvalidOperationException("Invalid sessionKey");
                        }

                        if (model == null || model.Store == null || model.Store == "")
                        {
                            throw new ArgumentOutOfRangeException("Missing Data.");
                        }

                        var store = context.Stores
                            .FirstOrDefault(x=>x.StoreName.ToLower() == model.Store.ToLower());

                        if (store == null)
                        {
                            throw new ArgumentOutOfRangeException("Missing Data.");
                        }

                        var book = new Book
                        {
                            Title = model.Title,
                            Author = model.Author,
                            Genre = model.Genre,
                            Pages = model.Pages,
                            Store = store,
                            IsAvailable = true
                        };

                        book = context.Books.Add(book);
                        context.SaveChanges();

                        var response =
                            this.Request.CreateResponse(HttpStatusCode.Created,
                                            book.Id);
                        return response;
                    }
                });

            return responseMsg;
        }
    }
}
